package com.schoolvisitors.service;

import com.alibaba.fastjson2.JSONObject;
import com.schoolvisitors.dto.AdminDto;
import com.schoolvisitors.dto.AdminLoginDto;
import com.schoolvisitors.entity.Admin;
import com.schoolvisitors.entity.LoginToken;
import com.schoolvisitors.entity.Role;
import com.schoolvisitors.exception.BusinessException;
import com.schoolvisitors.repository.AdminRepository;
import com.schoolvisitors.repository.LoginTokenRepository;
import com.schoolvisitors.repository.RoleRepository;
import com.schoolvisitors.response.ResultCode;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Slf4j
@Service
public class AdminService {

    private final RoleRepository roleRepository;
    private final AdminRepository adminRepository;
    private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    private final LoginTokenRepository loginTokenRepository;

    public AdminService(RoleRepository roleRepository, AdminRepository adminRepository, LoginTokenRepository loginTokenRepository) {
        this.roleRepository = roleRepository;
        this.adminRepository = adminRepository;
        this.loginTokenRepository = loginTokenRepository;
    }

    // @param adminDto 管理员DTO对象
    public void createAdmin(AdminDto adminDto) {
        // 查找角色
        Role role = roleRepository.findById(adminDto.getRoleId()).orElseThrow(() -> new BusinessException(ResultCode.ROLE_NOT_FOUND));
        if (adminRepository.findByUsername((adminDto.getUsername())).isPresent()){
            throw new BusinessException(ResultCode.ADMIN_USERNAME_IS_USE);
        }
        // 创建新管理员
        Admin admin = new Admin();
        admin.setUsername(adminDto.getUsername());
        admin.setPassword(encoder.encode(adminDto.getPassword()));
        admin.setRealName(adminDto.getRealName());
        admin.setReviewer(adminDto.getReviewer());
        admin.setRole(role);
        admin.setCreateTime(LocalDateTime.now());
        adminRepository.save(admin);
    }

    /**
     * 删除指定ID的管理员
     * @param adminId 管理员ID
     */
    @Transactional
    public void deleteAdmin(Long adminId) {
        Admin admin = adminRepository.findById(adminId).orElseThrow(() -> new BusinessException(ResultCode.ADMIN_NOT_FOUND));
        loginTokenRepository.deleteByRoleAndIndexId("admin", adminId);
        admin.setDelete(true);
        adminRepository.save(admin);
    }

    public List<Admin> getAdmins() {
        return adminRepository.findAllByDeleteFalse();
    }

    public JSONObject login(@Valid AdminLoginDto adminLoginDto) {
        // String hashPassword = encoder.encode(adminLoginDto.getPassword());
        log.info("管理员登录: {} {}", adminLoginDto.getUsername(), adminLoginDto.getPassword());
        // log.info("加密的密码 {}", hashPassword);
        Admin admin = adminRepository.findByUsernameAndDeleteFalse(adminLoginDto.getUsername()).orElseThrow(() -> new BusinessException(ResultCode.ADMIN_NOT_FOUND));

        if (!encoder.matches(adminLoginDto.getPassword(), admin.getPassword())) {
            throw new BusinessException(ResultCode.USERNAME_OR_PASSWORD_ERROR);
        }
        LoginToken loginToken = new LoginToken();
        loginToken.setRole("admin");
        loginToken.setIndexId(admin.getId());
        loginToken.setToken(makeToken());
        loginToken.setCreateTime(LocalDateTime.now());
        loginTokenRepository.save(loginToken);

        JSONObject data = new JSONObject();
        data.put("token", loginToken.getToken());
        data.put("permissions", admin.getRole().getPermissions());
        return data;
    }

    private String makeToken(){
        return UUID.randomUUID().toString().replace("-", "").substring(0, 32);
    }

    public Optional<Admin> findByAdminId(@NotNull Long indexId) {
        return adminRepository.findByIdAndDeleteFalse(indexId);
    }

    public void logout(Admin admin, String token) {
        LoginToken loginToken = loginTokenRepository.findByTokenAndRole(token, "admin");
        if (loginToken != null) {
            loginTokenRepository.delete(loginToken);
        }
    }

    public void updateAdmin(@Valid AdminDto adminDto) {
        Admin admin = adminRepository.findByIdAndDeleteFalse(adminDto.getId())
                .orElseThrow(() -> new BusinessException(ResultCode.ADMIN_NOT_FOUND));

        // 更新用户名
        if (!admin.getUsername().equals(adminDto.getUsername())) {
            // 检查用户名是否被其他管理员使用
            if (adminRepository.findByUsername(adminDto.getUsername()).isPresent()) {
                throw new BusinessException(ResultCode.ADMIN_USERNAME_IS_USE);
            }
            admin.setUsername(adminDto.getUsername());
        }

        admin.setRealName(adminDto.getRealName());
        admin.setReviewer(adminDto.getReviewer());
        // 更新密码，只有当密码不为空时才更新
        if (adminDto.getPassword() != null && !adminDto.getPassword().isEmpty()) {
            admin.setPassword(encoder.encode(adminDto.getPassword()));
        }

        Role role = roleRepository.findById(adminDto.getRoleId()).orElseThrow(() -> new BusinessException(ResultCode.ROLE_NOT_FOUND));
        admin.setRole(role);

        adminRepository.save(admin);
    }


//    /**
//     * 为管理员分配角色
//     *
//     * @param adminId 管理员ID
//     * @param roleId  角色ID
//     * @return 更新后的管理员对象
//     */
//    public Admin assignRoleToAdmin(Long adminId, Long roleId) {
//        Admin admin = adminRepository.findById(adminId)
//                .orElseThrow(() -> new EntityNotFoundException("Admin not found"));
//
//        Role role = roleRepository.findById(roleId)
//                .orElseThrow(() -> new EntityNotFoundException("Role not found"));
//
//        admin.setRole(role);
//        return adminRepository.save(admin);
//    }
//
//    /**
//     * 删除管理员的角色
//     * @param adminId 管理员ID
//     * @return 更新后的管理员对象
//     */
//    public Admin removeRoleFromAdmin(Long adminId) {
//        Admin admin = adminRepository.findById(adminId)
//                .orElseThrow(() -> new EntityNotFoundException("Admin not found"));
//
//        admin.setRole(null);  // 移除角色
//        return adminRepository.save(admin);
//    }
}
